package com.xiaoxi.bms.common.config;

import com.xiaoxi.bms.common.filter.JwtAuthorizationTokenFilter;
import com.xiaoxi.bms.common.filter.ValidateCodeFilter;
import com.xiaoxi.bms.common.handler.BMSSecurityAuthenticationEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.header.Header;
import org.springframework.security.web.header.writers.StaticHeadersWriter;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * @ClassName SecurityConfig
 * @Description 安全策略
 * @Author xiaoxi
 * @Date 2022/4/24 14:24
 * @Version 1.0
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private BMSSecurityAuthenticationEntryPoint bmsSecurityAuthenticationEntryPoint;

    @Resource
    private JwtAuthorizationTokenFilter jwtAuthorizationTokenFilter;

    @Resource
    private ValidateCodeFilter validateCodeFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        //以下五步是表单登录进行身份认证最简单的登陆环境
        http.formLogin()  // 1. 表单登陆
                .loginPage("http://localhost:8080/#/login")   // 1.1 指定登陆页面
                .and()        // 2.
                .authorizeRequests()    // 3. 下面的都是授权的配置
                .antMatchers("/user/api/v1/login", "/code/api/v1/getVerificationCode", "/user/api/v1/changeUserPassword").permitAll()  // 3.1 针对后台管理系统，是没有注册按钮的，只能在管理系统里面注册
                .anyRequest()           // 4. 任何请求
                .authenticated()        // 5. 访问任何资源都需要身份认证
                .and()
                .csrf().disable();      //防御策略  关闭跨站请求伪造攻击拦截


        // 在执行 安全策略 先筛选一遍
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(jwtAuthorizationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        // AuthenticationEntryPoint 该类用来统一处理 AuthenticationException 异常
        // AccessDeniedHandler 该类用来统一处理 AccessDeniedException 异常   （暂时不需要）
        http.exceptionHandling().authenticationEntryPoint(bmsSecurityAuthenticationEntryPoint);

        http.headers()
                .frameOptions().and()
                .addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
                        // 解决跨域问题
                        new Header("Access-control-Allow-Origin", "*")
                        , new Header("Access-control-Allow-Credentials", "true"))));

    }

    /**
     * SpringSecurity 密码加密
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
